package com.briup.tuixiangzi;



import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;

public class Pushbox005 extends JFrame implements KeyListener, ActionListener, MouseListener {

    //    定义一个内部类用来创建坐标
    class Point{
        public int x;
        public int y;
        public Point (int x,int y){
            this.x=x;
            this.y=y;
        }
    }
    //    行数(高）
    int height=8;
    //    列数（宽）
    int width=8;
    //    格子的大小
    int size=50;
    //    标题栏的高度
    int title=100;


    //    记录窗口大小是否发生改变
    boolean window=false;

    //    关卡地图信息
    class Ditu{
        public int [][] ditu;
        Ditu(int[][] _ditu){
            this.ditu=_ditu;
        }
    }

    //    创建一个二维数组用来存放关卡
//    1-10关地图
    int [][] ditu1={{0,0,1,1,1,0,0,0},{0,0,1,3,1,0,0,0},{0,0,1,2,1,1,1,1},{1,1,1,4,2,4,3,1},{1,3,2,4,5,1,1,1},{1,1,1,1,4,1,0,0},{0,0,0,1,3,1,0,0},{0,0,0,1,1,1,0,0}};
    int [][] ditu2= {{1,1,1,1,1,0,0,0,0},{1,2,2,5,1,0,0,0,0},{1,2,4,4,1,0,1,1,1},{1,2,4,2,1,0,1,3,1},{1,1,1,2,1,1,1,3,1},{0,1,1,2,2,2,2,3,1},{0,1,2,2,2,1,2,2,1},{0,1,2,2,2,1,1,1,1},{0,1,1,1,1,1,0,0,0}};
    int [][] ditu3={{0,1,1,1,1,1,1,1,0,0},{0,1,2,2,2,2,2,1,1,1},{1,1,4,1,1,1,2,2,2,1},{1,2,5,2,4,2,2,4,2,1},{1,2,3,3,1,2,4,2,1,1},{1,1,3,3,1,2,2,2,1,0},{0,1,1,1,1,1,1,1,1,0}};
    int [][] ditu4={{0,1,1,1,1,0},{1,1,2,2,1,0},{1,5,4,2,1,0},{1,1,4,2,1,1},{1,1,2,4,2,1},{1,3,4,2,2,1},{1,3,3,6,3,1},{1,1,1,1,1,1}};
    int [][] ditu5={{0,1,1,1,1,1,0,0},{0,1,2,2,1,1,1,0},{0,1,5,4,2,2,1,0},{1,1,1,2,1,2,1,1},{1,3,1,2,1,2,2,1},{1,3,4,2,2,1,2,1},{1,3,2,2,2,4,2,1},{1,1,1,1,1,1,1,1}};
    int [][] ditu6={{0,0,0,1,1,1,1,1,1,1,0,0,0},{1,1,1,1,2,2,2,2,2,1,0,0,0},{1,2,2,2,3,1,1,1,2,1,0,0,0},{1,2,1,2,1,2,2,2,2,1,1,0,0},{1,2,1,2,4,2,4,1,3,2,1,0,0},{1,2,1,2,2,6,2,2,1,2,1,0,0},{1,2,3,1,4,2,4,2,1,2,1,0,0},{1,1,2,2,2,2,1,2,1,2,1,1,1},{0,1,2,1,1,1,3,2,2,2,2,5,1},{0,1,2,2,2,2,2,1,1,2,2,2,1},{0,1,1,1,1,1,1,1,1,1,1,1,1}};
    int [][] ditu7={{0,0,0,1,1,1,1,1,1,1},{0,0,1,1,2,2,1,2,5,1},{0,0,1,2,2,2,1,2,2,1},{0,0,1,4,2,4,2,4,2,1},{0,0,1,2,4,1,1,2,2,1},{1,1,1,2,4,2,1,2,1,1},{1,3,3,3,3,3,2,2,1,0},{1,1,1,1,1,1,1,1,1,0}};
    int [][] ditu8={{0,0,0,1,1,1,1,1,1,0},{0,1,1,1,2,2,2,2,1,0},{1,1,3,2,4,1,1,2,1,1},{1,3,3,4,2,4,2,2,5,1},{1,3,3,2,4,2,4,2,1,1},{1,1,1,1,1,1,2,2,1,0},{0,0,0,0,0,1,1,1,1,0}};
    int [][] ditu9={{0,1,1,1,1,1,1,1,1,1,0},{0,1,2,2,1,1,2,2,2,1,0},{0,1,2,2,2,4,2,2,2,1,0},{0,1,4,2,1,1,1,2,4,1,0},{0,1,2,1,3,3,3,1,2,1,0},{1,1,2,1,3,3,3,1,2,1,1},{1,2,4,2,2,4,2,2,4,2,1},{1,2,2,2,2,2,1,2,5,2,1},{1,1,1,1,1,1,1,1,1,1,1}};
    int [][] ditu10={{0,0,1,1,1,1,1,1},{0,0,1,2,2,2,2,1},{1,1,1,4,4,4,2,1},{1,5,2,4,3,3,2,1},{1,2,4,3,3,3,1,1},{1,1,1,1,2,2,1,0},{0,0,0,1,1,1,1,0}};
    //    创建一个总地图
    Ditu ditu[]={new Ditu(ditu1),new Ditu(ditu2),new Ditu(ditu3),new Ditu(ditu4),new Ditu(ditu5),new Ditu(ditu6),new Ditu(ditu7),new Ditu(ditu8),new Ditu(ditu9),new Ditu(ditu10)};

    //    定义一个当前关卡
    int guan=1;

    //    定义一个最大关卡
    int maxguan=10;

    //   定义一个变量判断是否通关
    boolean tongguan=false;

    //    创建一个推箱子的小人
    Point man=new Point(4,4);

    //    创建箱子
    Point [] box= {new Point(3,3),new Point(3,4),new Point(5,3),new Point(4,5)};

    //    创建箱子最终要到达的位置
    Point [] home={new Point(1,4),new Point(3,1),new Point(6,3),new Point(4,6)};

    //    创建一个墙壁数组
    Point [] qiangbi= {new Point(2,0),new Point(3,0),new Point(4,0),
            new Point(2,1),new Point(4,1),
            new Point(2,2),new Point(4,2),new Point(5,2),new Point(6,2),new Point(7,2),
            new Point(0,3),new Point(1,3),new Point(2,3),new Point(7,3),
            new Point(0,4), new Point(5,4), new Point(6,4), new Point(7,4),
            new Point(0,5),new Point(1,5),new Point(2,5),new Point(3,5),new Point(5,5),
            new Point(3,6),new Point(5,6),
            new Point(3,7),new Point(4,7),new Point(5,7)
    };

    //    创建一个空地数组
    Point [] kongdi={new Point(3,1),
            new Point(3,2),
            new Point(3,3),new Point(4,3),new Point(5,3),new Point(6,3),
            new Point(1,4),new Point(2,4),new Point(3,4),new Point(4,4),
            new Point(4,5),
            new Point(4,6)
    };


    //    设置图片
    private Image image=null;
    Graphics gf=null;

    //    设置计时器
    Timer timer=new Timer(500,this);
    public void Tian(){
//      加载地图
        jiazaiditu(guan);
        //设置窗口的宽高
        this.setSize(width*size ,height*size+title);
//        设置标题
        this.setTitle("推箱子");
        //设置窗口能看见
        this.setVisible(true);
//        设置窗口顶点坐标的位置
        this.setLocation(100,100);
        //设置键盘监听事件（也就是当键盘有什么反应都会调用此函数）
        this.addKeyListener(this);
    }

    public void paint(Graphics g){

        // 窗口大小改变后，重新创建缓存图片
        if(window == true) {
            window = false;
            image=this.createImage(width*size,height*size+title);
            this.gf =image.getGraphics();
        }

        //初始化临时图片//解决闪烁问题
        if(image==null){
            image=this.createImage(width*size,height*size+title);
        }
        if(this.gf ==null){
            this.gf =image.getGraphics();
        }

        //        擦除背景
        gf.setColor(Color.white);
        gf.fill3DRect(0,0,width*size,title+height*size,true);

        //        绘制网格
        gf.setColor(Color.GRAY);
//        画行（画横线）
//        for (int i = 0; i <= height; i++) {
//            gf.drawLine(0,size*i+title,width*size,size*i+title);
//        }
     //   画列（画竖线）
//        for (int i = 0; i <= width; i++) {
//            gf.drawLine(i*size,title,i*size,height*size+title);
//        }

//       绘制墙
        for (int i = 0; i <qiangbi.length ; i++) {
            gf.setColor(Color.pink);
            gf.fill3DRect(qiangbi[i].x*size,qiangbi[i].y*size+title,size,size,true);
        }
        //       绘制箱子最终要到达的位置
        for (int i = 0; i <home.length ; i++) {
            gf.setColor(Color.black);
            gf.drawOval(home[i].x*size,home[i].y*size+title,size,size);
            gf.drawLine(home[i].x*size,home[i].y*size+title,home[i].x*size+size,home[i].y*size+title+size);
        }
//        绘制真实的箱子
        for (int i = 0; i <box.length ; i++) {
            gf.setColor(Color.ORANGE);
            gf.fill3DRect(box[i].x*size,box[i].y*size+title,size,size,true);
            if(isguiwei(i)){
                gf.setColor(Color.red);
                gf.fill3DRect(box[i].x*size,box[i].y*size+title,size,size,true);

            }
        }
//        绘制推箱子的小人
        gf.setColor(Color.green);
        gf.fillOval(man.x*size,man.y*size+title,size,size);

//        绘制当前关卡信息
        if(iswin()==true&&tongguan==true){
            gf.setColor(Color.darkGray);
            gf.fill3DRect(0,0,width*size,title,true);
            gf.setFont(new Font("华文新魏", 10, 55)); //设置字体
            gf.setColor(Color.white);
            gf.drawString("恭喜通关",width*size/2-110,title/2+40);
        }else {
            gf.setColor(Color.darkGray);
            gf.fill3DRect(0,0,width*size,title,true);
            gf.setFont(new Font("华文新魏", 10, 55)); //设置字体
            gf.setColor(Color.white);
            gf.drawString("弟"+guan+"关",width*size/2-82,title/2+40);
        }

        g.drawImage(image,0,0,null);

    }

    //    按下键盘--控制游戏的开始以及方块的移动方向
    public void keyPressed(KeyEvent e) {
        // 获取从键盘输入的键
        int key = e.getKeyCode();
        //       上
        if (key == KeyEvent.VK_UP) {
//            y-1是空地
            if(iscunzai(kongdi,new Point(man.x,man.y-1))==true){
//                y-1是空地，且空地上没有箱子
                if(iscunzai(box,new Point(man.x,man.y-1))==false){
                    man.y--;
                }else{//y-2是一个空地，且没有箱子
//                    y-2是一个没有箱子的空地(这种就是上边已经有了一个箱子，箱子的上边再没有箱子且是空地)
                    if ((iscunzai(kongdi,new Point(man.x,man.y-2))==true)&&(iscunzai(box,new Point(man.x,man.y-2))==false)){
//                      这种情况下是人和箱子都向上移动一格
                        for (int i = 0; i < box.length; i++) {
                            if(box[i].x==man.x&&box[i].y==man.y-1){
                                box[i].y--;
                                break;
                            }
                        }
                        man.y--;
                        //判断所有箱子是否归位
                        if(iswin()==true){

                            if(guan<maxguan){//不是最后一关

                                guan++;
//                            加载新一关的地图
                                jiazaiditu(guan);
                            }else{//是最后一关
                                tongguan=true;
                            }

                        }

                    }
                }
            }

//        下
        }else if (key == KeyEvent.VK_DOWN) {
            //            y-1是空地
            if(iscunzai(kongdi,new Point(man.x,man.y+1))==true){
//                y-1是空地，且空地上没有箱子
                if(iscunzai(box,new Point(man.x,man.y+1))==false){
                    man.y++;
                }else{//y-2是一个空地，且没有箱子
//                    y-2是一个没有箱子的空地(这种就是上边已经有了一个箱子，箱子的上边再没有箱子且是空地)
                    if ((iscunzai(kongdi,new Point(man.x,man.y+2))==true)&&(iscunzai(box,new Point(man.x,man.y+2))==false)){
//                      这种情况下是人和箱子都向上移动一格
                        for (int i = 0; i < box.length; i++) {
                            if(box[i].x==man.x&&box[i].y==man.y+1){
                                box[i].y++;
                                break;
                            }
                        }
                        man.y++;
                        //判断所有箱子是否归位
                        if(iswin()==true){
                            if(guan<maxguan){
                                guan++;
//                            加载新一关的地图
                                jiazaiditu(guan);
                            }else{
                                tongguan=true;
                            }

                        }

                    }
                }
            }
//            左
        }else if(key == KeyEvent.VK_LEFT){
            if(iscunzai(kongdi,new Point(man.x-1,man.y))==true){
//                y-1是空地，且空地上没有箱子
                if(iscunzai(box,new Point(man.x-1,man.y))==false){
                    man.x--;
                }else{//y-2是一个空地，且没有箱子
//                    y-2是一个没有箱子的空地(这种就是上边已经有了一个箱子，箱子的上边再没有箱子且是空地)
                    if ((iscunzai(kongdi,new Point(man.x-2,man.y))==true)&&(iscunzai(box,new Point(man.x-2,man.y))==false)){
//                      这种情况下是人和箱子都向上移动一格
                        for (int i = 0; i < box.length; i++) {
                            if(box[i].x==man.x-1&&box[i].y==man.y){
                                box[i].x--;
                                break;
                            }
                        }
                        man.x--;
                        //判断所有箱子是否归位
                        if(iswin()==true){
                            if(guan<maxguan){
                                guan++;
//                            加载新一关的地图
                                jiazaiditu(guan);
                            }else{
                                tongguan=true;
                            }

                        }

                    }
                }
            }

//            右
        }else if (key == KeyEvent.VK_RIGHT) {
            if(iscunzai(kongdi,new Point(man.x+1,man.y))==true){
//                y-1是空地，且空地上没有箱子
                if(iscunzai(box,new Point(man.x+1,man.y))==false){
                    man.x++;
                }else{//y-2是一个空地，且没有箱子
//                    y-2是一个没有箱子的空地(这种就是上边已经有了一个箱子，箱子的上边再没有箱子且是空地)
                    if ((iscunzai(kongdi,new Point(man.x+2,man.y))==true)&&(iscunzai(box,new Point(man.x+2,man.y))==false)){
//                      这种情况下是人和箱子都向上移动一格
                        for (int i = 0; i < box.length; i++) {
                            if(box[i].x==man.x+1&&box[i].y==man.y){
                                box[i].x++;
                                break;
                            }
                        }
                        man.x++;
                        //判断所有箱子是否归位
                        if(iswin()==true){
                            if(guan<maxguan){
                                guan++;
//                            加载新一关的地图
                                jiazaiditu(guan);
                            }else{
                                tongguan=true;
                            }
                        }
                    }
                }
            }

        }
//        点击空格键重玩当前关卡
        if(key == KeyEvent.VK_SPACE) {//空格键
//            重置当前关卡
            jiazaiditu(guan);
        }
        repaint();
    }
    public void keyReleased(KeyEvent e) {
    }
    public void mouseClicked(MouseEvent e) {
    }
    public void mousePressed(MouseEvent e) {
    }
    public void mouseReleased(MouseEvent e) {
    }
    public void mouseEntered(MouseEvent e) {
    }
    public void mouseExited(MouseEvent e) {
    }
    //   判断某个数组中是否存在某个点
//    判断point这个点是否在points这个数组中
    public boolean iscunzai(Point [] points,Point point){
        for (int i = 0; i < points.length; i++) {
            if(points[i].x==point.x&&points[i].y==point.y){
                return true;
            }
        }
        return false;
    }


    //    加载地图
    public void jiazaiditu(int index){
        // 清空当前数据
        //
        ArrayList<Point> boxlist = new ArrayList<Point>();
        ArrayList<Point> homelist = new ArrayList<Point>();
        ArrayList<Point> qiangbilist = new ArrayList<Point>();
        ArrayList<Point> kongdilist = new ArrayList<Point>();

        Ditu d = ditu[index-1];
        for(int i= 0;i<d.ditu.length;i++)
        {
            for(int j=0;j<d.ditu[i].length;j++)
            {
                // 1是墙壁
                if(d.ditu[i][j] == 1){
                    qiangbilist.add(new Point(j,i));
                }
                // 2是空地
                else if(d.ditu[i][j] == 2){
                    kongdilist.add(new Point(j,i));
                }
                // 3是黑店
                else if(d.ditu[i][j] == 3){
                    homelist.add(new Point(j,i));
                    kongdilist.add(new Point(j,i));
                }
                // 4箱子
                else if(d.ditu[i][j] == 4){
                    boxlist.add(new Point(j,i));
                    kongdilist.add(new Point(j,i));
                }
                // 5人
                else if(d.ditu[i][j] == 5){
                    man.x = j;
                    man.y = i;
                    kongdilist.add(new Point(j,i));
                }
                // 6(箱子在黑点上)
                else if(d.ditu[i][j] ==6){
                    boxlist.add(new Point(j,i));
                    kongdilist.add(new Point(j,i));
                    homelist.add(new Point(j,i));
                }
                // 7（人在黑点上）
                else if(d.ditu[i][j] == 7){
                    man.x = j;
                    man.y = i;
                    kongdilist.add(new Point(j,i));
                    homelist.add(new Point(j,i));
                }
            }
        }
        int i=0;
        qiangbi = new Point[qiangbilist.size()];
        for (Point p:qiangbilist){
            qiangbi[i] = new Point(p.x,p.y);
            i++;
        }
        i=0;

        kongdi = new Point[kongdilist.size()];
        for (Point p:kongdilist){
            kongdi[i]=new Point(p.x,p.y);
            i++;
        }
        i=0;
        box = new Point[boxlist.size()];
        for (Point p:boxlist){
            box[i]=new Point(p.x,p.y);
            i++;
        }
        i=0;
        home = new Point[homelist.size()];
        for (Point p:homelist){
            home[i]=new Point(p.x,p.y);
            i++;
        }

        height=d.ditu.length;
        width=d.ditu[0].length;

        this.setSize(width*size,height*size+title);
        window=true;
    }

    //    判断单个方块是否归位//用于改变颜色
    public boolean isguiwei(int i){
        for (int i1 = 0; i1 < home.length; i1++) {
            if(box[i].x==home[i1].x&&box[i].y==home[i1].y){
                return true;
            }
        }
        return false;
    }

    public void actionPerformed(ActionEvent e) {
    }
    public void keyTyped(KeyEvent e) {
    }
    //    判断游戏是否胜利（判断方块是否全部归位）
    public boolean iswin(){
        int j=0;
        for (int i = 0; i < box.length; i++) {
            for (int i1 = 0; i1 < home.length; i1++) {
                if(box[i].x==home[i1].x&&box[i].y==home[i1].y){
                    j++;
                    if(j==home.length){
                        return true;
                    }
                }
            }
        }
        return false;
    }

    public static void main(String[] args) {
        Pushbox005 pushbox=new Pushbox005();
        pushbox.Tian();
    }

}

